libobs_wrapper\scenes\scene_item/
traits.rs

1use crate::scenes::{ObsSceneItemRef, ObsSceneRef, SceneItemTrait};
2use crate::sources::{ObsSourceRef, ObsSourceTrait};
3use crate::utils::{ObsError, SourceInfo};
4use std::sync::Arc;
5
6pub trait SceneItemExtSceneTrait {
7    /// Adds the specified source to this scene. Returns a reference to the created scene item.
8    /// You can use that SceneItemPtr to manipulate the source within this scene (position, scale, rotation, etc).
9    fn add_source<T: ObsSourceTrait + Clone + 'static>(
10        &mut self,
11        source: T,
12    ) -> Result<ObsSceneItemRef<T>, ObsError>;
13
14    /// Creates and adds a source to this scene based on the given `SourceInfo`.
15    /// Returns a reference to the created scene item, which internally holds the created source.
16    fn add_and_create_source(
17        &mut self,
18        info: SourceInfo,
19    ) -> Result<ObsSceneItemRef<ObsSourceRef>, ObsError>;
20
21    /// Gets a source by name from this scene. Returns None if no source with the given name exists in this scene.
22    fn get_source_mut(&self, name: &str) -> Result<Option<Arc<Box<dyn ObsSourceTrait>>>, ObsError>;
23
24    /// Removes the given source from this scene. Removes the corresponding scene item as well. It may be possible that this source is still added to another scene.
25    fn remove_every_item_of_source<T: ObsSourceTrait>(&mut self, source: T)
26        -> Result<(), ObsError>;
27
28    /// Removes a specific scene item from this scene.
29    fn remove_scene_item<K: SceneItemTrait>(&mut self, scene_item: K) -> Result<(), ObsError>;
30
31    /// Removes all sources from this scene.
32    fn remove_all_sources(&mut self) -> Result<(), ObsError>;
33
34    /// Gets the underlying scene item pointers for the given source in this scene.
35    ///
36    /// A scene item is basically the representation of a source within this scene. It holds information about the position, scale, rotation, etc.
37    fn get_scene_item_ptr<T: ObsSourceTrait + Clone>(
38        &self,
39        source: &T,
40    ) -> Result<Vec<Arc<Box<dyn SceneItemTrait>>>, ObsError>;
41}
42
43impl SceneItemExtSceneTrait for ObsSceneRef {
44    fn add_source<T: ObsSourceTrait + Clone + 'static>(
45        &mut self,
46        source: T,
47    ) -> Result<ObsSceneItemRef<T>, ObsError> {
48        let scene_item = ObsSceneItemRef::new(self, source.clone(), self.runtime.clone())?;
49
50        let scene_clone = scene_item.clone();
51        self.attached_scene_items
52            .write()
53            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
54            .entry(Arc::new(Box::new(source)))
55            .or_insert_with(Vec::new)
56            .push(Arc::new(Box::new(scene_clone)));
57
58        Ok(scene_item)
59    }
60
61    fn add_and_create_source(
62        &mut self,
63        info: SourceInfo,
64    ) -> Result<ObsSceneItemRef<ObsSourceRef>, ObsError> {
65        let source = crate::sources::ObsSourceRef::new(
66            info.id,
67            info.name,
68            info.settings,
69            info.hotkey_data,
70            self.runtime.clone(),
71        )?;
72
73        let scene_item = self.add_source(source.clone())?;
74        Ok(scene_item)
75    }
76
77    fn get_source_mut(&self, name: &str) -> Result<Option<Arc<Box<dyn ObsSourceTrait>>>, ObsError> {
78        let r = self
79            .attached_scene_items
80            .read()
81            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
82            .keys()
83            .find(|s| s.name() == name)
84            .cloned();
85
86        Ok(r)
87    }
88
89    fn remove_every_item_of_source<T: ObsSourceTrait>(
90        &mut self,
91        source: T,
92    ) -> Result<(), ObsError> {
93        let source_ptr = source.as_ptr().get_ptr();
94
95        self.attached_scene_items
96            .write()
97            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
98            .retain(|s, _| {
99                //TODO: Maybe find a better way to utilize the HashMap's capabilities here
100                s.as_ptr().get_ptr() != source_ptr
101            });
102
103        Ok(())
104    }
105
106    fn remove_scene_item<K: SceneItemTrait>(&mut self, scene_item: K) -> Result<(), ObsError> {
107        let mut guard = self
108            .attached_scene_items
109            .write()
110            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
111
112        guard.retain(|_, items| {
113            items.retain(|item| {
114                // Keep everything except this one scene item
115                item.as_ptr().get_ptr() != scene_item.as_ptr().get_ptr()
116            });
117            // Remove the entry if no items remain
118            !items.is_empty()
119        });
120        Ok(())
121    }
122
123    fn remove_all_sources(&mut self) -> Result<(), ObsError> {
124        // Dropping the scene items is handled by the smart pointer drop guards
125        self.attached_scene_items
126            .write()
127            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
128            .clear();
129
130        Ok(())
131    }
132
133    fn get_scene_item_ptr<T: ObsSourceTrait + Clone>(
134        &self,
135        source: &T,
136    ) -> Result<Vec<Arc<Box<dyn SceneItemTrait>>>, ObsError> {
137        let guard = self
138            .attached_scene_items
139            .read()
140            .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
141
142        let res = guard
143            .iter()
144            .find_map(|(s, scene_item_pointers)| {
145                if s.as_ptr().get_ptr() == source.as_ptr().get_ptr() {
146                    Some(scene_item_pointers.clone())
147                } else {
148                    None
149                }
150            })
151            .unwrap_or_else(Vec::new);
152
153        Ok(res)
154    }
155}